﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using LeadThing.AbpZeroTemplate.ArticleCategorys;
using LeadThing.AbpZeroTemplate.Articles.Authorization;
using LeadThing.AbpZeroTemplate.Articles.Dtos;
using LeadThing.AbpZeroTemplate.Dto;
using LeadThing.AbpZeroTemplate.Files;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Threading.Tasks;
using static LeadThing.AbpZeroTemplate.Configuration.AppSettings;

namespace LeadThing.AbpZeroTemplate.Articles
{
    /// <summary>
    /// 文章服务实现
    /// </summary>

    public class ArticleAppService : AbpZeroTemplateAppServiceBase, IArticleAppService
    {
        private readonly IRepository<Article, long> _articleRepository;
        private readonly IArticleListExcelExporter _articleListExcelExporter;
        private readonly IRepository<ArticleCategory, long> _articleCategoryRepository;
        private readonly IRepository<File, long> _fileRepository;
        private readonly ArticleManage _articleManage;

        /// <summary>
        /// 构造方法
        /// </summary>
        public ArticleAppService(IRepository<Article, long> articleRepository,
        ArticleManage articleManage,
        IArticleListExcelExporter articleListExcelExporter,
        IRepository<ArticleCategory, long> articleCategoryRepository,
        IRepository<File, long> fileRepository
  )
        {
            _articleRepository = articleRepository;
            _articleManage = articleManage;
            _articleListExcelExporter = articleListExcelExporter;
            _articleCategoryRepository = articleCategoryRepository;
            _fileRepository = fileRepository;
        }

        #region 实体的自定义扩展方法

        private IQueryable<Article> _articleRepositoryAsNoTrack => _articleRepository.GetAll().AsNoTracking();

        #endregion 实体的自定义扩展方法

        #region 文章管理

        /// <summary>
        /// 根据查询条件获取文章分页列表
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article)]
        public async Task<PagedResultDto<ArticleListDto>> GetPagedArticlesAsync(GetArticleInput input)
        {
            var query = _articleRepositoryAsNoTrack;
            //TODO:根据传入的参数添加过滤条件
            if (!string.IsNullOrWhiteSpace(input.Filter))
                query = query.Where(p => p.Title.Contains(input.Filter));

            var articleCount = await query.CountAsync();

            var articles = await query
            .OrderByDescending(p => p.SortId)
            .OrderByDescending(p => p.Id)
            .PageBy(input)
            .ToListAsync();

            var articleCategoryList = _articleCategoryRepository.GetAll();

            return new PagedResultDto<ArticleListDto>(
            articleCount,
            articles.Select(item =>
            {
                var dto = item.MapTo<ArticleListDto>();

                var articleCategoryModel = articleCategoryList.Where(p => p.Id == dto.CategoryId).FirstOrDefault();
                if (articleCategoryModel != null)
                    dto.CategoryTitle = articleCategoryModel.Title;

                return dto;
            }).ToList());
        }

        /// <summary>
        /// 通过Id获取文章信息进行编辑或修改
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article)]
        public async Task<GetArticleForEditOutput> GetArticleForEditAsync(NullableIdDto<long> input)
        {
            var output = new GetArticleForEditOutput();

            ArticleEditDto articleEditDto;

            if (input.Id.HasValue)
            {
                var entity = await _articleRepository.GetAsync(input.Id.Value);
                articleEditDto = entity.MapTo<ArticleEditDto>();
            }
            else
            {
                articleEditDto = new ArticleEditDto();
            }

            output.Article = articleEditDto;
            return output;
        }

        /// <summary>
        /// 通过指定id获取文章ListDto信息
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article)]
        public async Task<ArticleListDto> GetArticleByIdAsync(EntityDto<long> input)
        {
            var entity = await _articleRepository.GetAsync(input.Id);

            return entity.MapTo<ArticleListDto>();
        }

        /// <summary>
        /// 新增或更改文章
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article)]
        public async Task CreateOrUpdateArticleAsync(CreateOrUpdateArticleInput input)
        {
            if (input.ArticleEditDto.Id.HasValue)
            {
                await UpdateArticleAsync(input.ArticleEditDto);
            }
            else
            {
                await CreateArticleAsync(input.ArticleEditDto);
            }
        }

        /// <summary>
        /// 新增文章
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article_CreateArticle)]
        public virtual async Task<ArticleEditDto> CreateArticleAsync(ArticleEditDto input)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = input.MapTo<Article>();

            entity = await _articleRepository.InsertAsync(entity);
            return entity.MapTo<ArticleEditDto>();
        }

        /// <summary>
        /// 编辑文章
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article_EditArticle)]
        public virtual async Task UpdateArticleAsync(ArticleEditDto input)
        {
            //TODO:更新前的逻辑判断，是否允许更新

            var entity = await _articleRepository.GetAsync(input.Id.Value);
            input.MapTo(entity);

            await _articleRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除文章
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article_DeleteArticle)]
        public async Task DeleteArticleAsync(EntityDto<long> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            await _articleRepository.DeleteAsync(input.Id);
        }

        /// <summary>
        /// 批量删除文章
        /// </summary>
        [AbpAuthorize(ArticleAppPermissions.Article_DeleteArticle)]
        public async Task BatchDeleteArticleAsync(List<long> input)
        {
            //TODO:批量删除前的逻辑判断，是否允许删除
            await _articleRepository.DeleteAsync(s => input.Contains(s.Id));
        }

        #endregion 文章管理

        #region 文章的Excel导出功能

        public async Task<FileDto> GetArticleToExcel()
        {
            var entities = await _articleRepository.GetAll().ToListAsync();

            var dtos = entities.MapTo<List<ArticleListDto>>();

            var fileDto = _articleListExcelExporter.ExportArticleToFile(dtos);

            return fileDto;
        }

        #endregion 文章的Excel导出功能

        #region APP

        /// <summary>
        /// 根据查询条件获取文章分页列表
        /// </summary>
        public async Task<PagedResultDto<ArticleAPPListDto>> GetPagedArticlesAPPAsync(GetArticleAPPInput input)
        {
            var _pageIndex = Convert.ToInt32(input.PageIndex);
            var _pageSize = Convert.ToInt32(input.PageSize);
            var query = _articleRepositoryAsNoTrack;
            //TODO:根据传入的参数添加过滤条件
            if (!string.IsNullOrWhiteSpace(input.Filter))
                query = query.Where(p => p.Title.Contains(input.Filter));

            if (!string.IsNullOrWhiteSpace(input.IsSlide))
            {
                var _isSlide = Convert.ToBoolean(input.IsSlide);
                query = query.Where(p => p.IsSlide == _isSlide);
            }

            var articleCount = await query.CountAsync();

            var articles = await query
            .OrderByDescending(p => p.SortId)
            .OrderByDescending(p => p.Id)
            .Take(_pageSize * _pageIndex).Skip(_pageSize * (_pageIndex - 1))
            .ToListAsync();

            var articleCategoryList = _articleCategoryRepository.GetAll();
            var fileList = _fileRepository.GetAll();

            return new PagedResultDto<ArticleAPPListDto>(
            articleCount,
            articles.Select(item =>
            {
                var dto = item.MapTo<ArticleAPPListDto>();

                var articleCategoryModel = articleCategoryList.Where(p => p.Id == dto.CategoryId).FirstOrDefault();
                if (articleCategoryModel != null)
                    dto.CategoryTitle = articleCategoryModel.Title;
                var fileModel = fileList.Where(p => p.Id == dto.FileID).FirstOrDefault();
                if (fileModel != null)
                    dto.ImgUrl = AppSetting.AppUrl + fileModel.Url;

                return dto;
            }).ToList());
        }

        /// <summary>
        /// 通过Id获取文章信息进行编辑或修改
        /// </summary>
        public async Task<ArticleAPPEditDto> GetArticleForEditAPPAsync(EntityDto<string> input)
        {
            ArticleAPPEditDto articleEditDto;

            if (!string.IsNullOrWhiteSpace(input.Id))
            {
                var id = Convert.ToInt32(input.Id);
                var entity = await _articleRepository.GetAsync(id);
                articleEditDto = entity.MapTo<ArticleAPPEditDto>();

                var articleCategoryModel = _articleCategoryRepository.GetAll().Where(p => p.Id == articleEditDto.CategoryId).FirstOrDefault();
                if (articleCategoryModel != null)
                    articleEditDto.CategoryTitle = articleCategoryModel.Title;

                var fileModel = _fileRepository.GetAll().Where(p => p.Id == articleEditDto.FileID).FirstOrDefault();
                if (fileModel != null)
                    articleEditDto.ImgUrl = AppSetting.AppUrl + fileModel.Url;
            }
            else
            {
                articleEditDto = new ArticleAPPEditDto();
            }

            return articleEditDto;
        }

        #endregion APP
    }
}